﻿using Zo.Exceptions;

namespace Zo.Queues
{
    /// <summary>
    /// 默认队列。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class DefaultQueue<T>
    {
        /// <summary>
        /// 数据。
        /// </summary>
        private readonly T[] _data;

        /// <summary>
        /// 开始位置。
        /// </summary>
        private int _position = 0;

        /// <summary>
        /// 初始化。
        /// </summary>
        /// <param name="size">队列大小。</param>
        public DefaultQueue(int size)
        {
            _data = new T[size];
        }

        /// <summary>
        /// 队列中的元素个数。
        /// </summary>
        public int Count { get; set; }

        /// <summary>
        /// 入队。
        /// </summary>
        /// <param name="item">元素。</param>
        public void Enqueue(T item)
        {
            if (Count >= _data.Length)
            {
                throw new MainApplicationException("队列已满");
            }

            var nextIndex = 0;

            if (Count > 0)
            {
                nextIndex = _position + Count;

                if (nextIndex > _data.Length)
                {
                    nextIndex = nextIndex - _data.Length;
                }
            }

            _data[nextIndex] = item;

            Count++;
        }

        /// <summary>
        /// 出队。
        /// </summary>
        /// <returns>元素。</returns>
        public T Dequeue()
        {
            if (Count <= 0)
            {
                throw new MainApplicationException("队列为空");
            }

            var result = _data[_position];

            _position++;

            if (_position >= Count)
            {
                _position = 0;
            }

            return result;
        }
    }
}